package com.imooc.long5zb.rest;


import com.imooc.long5zb.CheckUtil;
import com.imooc.long5zb.entity.MongoUser;
import com.imooc.long5zb.dao.MongoUserRepository;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.validation.Valid;

@RestController
@RequestMapping("/mongo_user/")
public class MongoUserController {

    private final MongoUserRepository repository;

    public MongoUserController(MongoUserRepository repository) {
        this.repository = repository;
    }

    /**
     * 以数组形式返回
     * @return
     */
    @GetMapping("all")
    public Flux<MongoUser> getAll() {
        return repository.findAll();
    }

    @GetMapping(value = "/stream/all", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<MongoUser> StreamGetAll() {
        return repository.findAll();
    }

    @GetMapping("{id}")
    public Mono<ResponseEntity<MongoUser>> findById(@PathVariable("id") String id) {
        return this.repository.findById(id)
                .map(user -> new ResponseEntity<MongoUser>(user, HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    /**
     * 根据年龄范围查找用户
     * @param start
     * @param end
     * @return
     */
    @GetMapping("age/{start}/{end}")
    public Flux<MongoUser> rangeByAge(@PathVariable("id") int start,
                                      @PathVariable("id") int end) {
        return this.repository.findByAgeBetween(start, end);
    }

    @GetMapping(value = "stream/age/{start}/{end}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<MongoUser> streamRangeByAge(@PathVariable("id") int start,
                                            @PathVariable("id") int end) {
        return this.repository.findByAgeBetween(start, end);
    }

    @GetMapping("old")
    public Flux<MongoUser> old() {
        return this.repository.oldUser();
    }

    @GetMapping(value = "stream/old", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<MongoUser> streamOld() {
        return this.repository.oldUser();
    }

    @PostMapping
    public Mono<MongoUser> createUser(@Valid @RequestBody MongoUser mongoUser) {
        mongoUser.setId(null);
        CheckUtil.checkName(mongoUser.getName());
        return repository.save(mongoUser);
    }

    @PutMapping("{id}")
    public Mono<ResponseEntity<MongoUser>> updateUser(@PathVariable("id") String id,
                                                      @Valid @RequestBody MongoUser mongoUser) {
        return this.repository.findById(id)
                .flatMap(user -> {
                    user.setAge(mongoUser.getAge());
                    user.setName(mongoUser.getName());
                    return this.repository.save(user);
                })
                .map(user -> new ResponseEntity<MongoUser>(HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    @DeleteMapping("{id}")
    public Mono<ResponseEntity<Void>> deleteUser(@PathVariable("id") String id) {
        return this.repository.findById(id)
                /**  当要操作数据，并返回一个Mono，这个时候使用flatMap，如果不操作数据，只转换数据，使用map**/
                .flatMap(user -> this.repository.delete(user))
                .then(Mono.just(new ResponseEntity<Void>(HttpStatus.OK)))
                .defaultIfEmpty(new ResponseEntity<Void>(HttpStatus.NOT_FOUND));
    }

}
